package com.boss.core;

import java.io.File;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.boss.core.Boss;
import com.boss.core.BossConstants;
import com.boss.core.BossDescriptor;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import net.sf.json.JSONObject;
import hudson.Extension;
import hudson.util.FormValidation;

import com.boss.Messages;

/**
 * Boss Global Properties- configured in Hudson's Admin page
 * @author Momin Noor Khan
 */
public class BossGlobal extends Boss {
    private static final Logger LOGGER = Logger.getLogger(BossGlobal.class.getName());

    @Override
    public String getDescription() {
        return "";
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    @Extension
    public static final class DescriptorImpl extends BossDescriptor {
        private String jobDelay;
        private String oc4jProfilesPath;
        private String pamOc4jProfilesPath;
        private String gisProfilesPath;
        private String svnUserName;
        private String svnPassword;

        public DescriptorImpl() {
            load();
        }

        @Override
        public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
            this.jobDelay = formData.getString("jobDelay");
            this.oc4jProfilesPath = formData.getString("oc4jProfilesPath");
            this.pamOc4jProfilesPath = formData.getString("pamOc4jProfilesPath");
            this.gisProfilesPath = formData.getString("gisProfilesPath");
            this.svnUserName = formData.getString("svnUserName");
            this.svnPassword = formData.getString("svnPassword");

            save();
            return super.configure(req, formData);
        }

        /**
         * Gets the job delay for BOSS jobs from the global configuration settings done in Hudson.
         * Returns the default value if its empty.
         *
         * @return
         */
        public String getJobDelay() {
            if (StringUtils.isBlank(jobDelay)) {
                String defaultJobDelay = BossConstants.DEFAULT_JOB_DELAY;
                return defaultJobDelay;
            } else {
                return jobDelay;
            }
        }

        /**
         * Gets the path of the OC4JProfiles where the properties file for each target container is stored
         *
         * @return
         */
        public String getOc4jProfilesPath() {
            if (StringUtils.isBlank(oc4jProfilesPath)) {
                String defaultOC4JProfilesPath = "";
                try {
                    defaultOC4JProfilesPath = System.getenv("CCS_AUXILIARY") + BossConstants.SERVER_PROFILES;
                }
                //do nothing even if either SecurityException or NullPointerException occurs and simply return empty defaultOC4JProfilesPath later
                catch (Exception e) {
                    LOGGER.log(Level.WARNING, "CCS_AUXILIARY environment variable not set. Default value of would be returned.", e);
                }
                return defaultOC4JProfilesPath;
            } else {
                if (!oc4jProfilesPath.endsWith(File.separator)) {
                    oc4jProfilesPath = oc4jProfilesPath.concat(File.separator);
                }
                return oc4jProfilesPath;
            }
        }

        /**
         * Gets the path of the OC4JProfiles where the properties file for each target container is stored
         *
         * @return
         */
        public String getGisProfilesPath() {
            if (StringUtils.isBlank(gisProfilesPath)) {
                String defaultGISProfilesPath = "";
                try {
                    defaultGISProfilesPath = System.getenv("CCS_AUXILIARY") + BossConstants.GIS_SERVER_PROFILES;
                }
                //do nothing even if either SecurityException or NullPointerException occurs and simply return empty defaultOC4JProfilesPath later
                catch (Exception e) {
                    LOGGER.log(Level.WARNING, "CCS_AUXILIARY environment variable not set. Default value of would be returned.", e);
                }
                return defaultGISProfilesPath;
            } else {
                if (!gisProfilesPath.endsWith(File.separator)) {
                    gisProfilesPath = gisProfilesPath.concat(File.separator);
                }
                return gisProfilesPath;
            }
        }

        /**
         * Get the username of SVN
         *
         * @return
         */
        public String getSvnUserName() {
            if (StringUtils.isBlank(svnUserName)) {
                return BossConstants.SVN_USERNAME;
            } else {
                return svnUserName;
            }
        }

        /**
         * Get the password of SVN corresponding to SVN username
         *
         * @return
         */
        public String getSvnPassword() {
            if (StringUtils.isBlank(svnPassword)) {
                return BossConstants.SVN_PASSWORD;
            } else {
                return svnPassword;
            }
        }

        /**
         * On-the-fly validation method for the global property 'Job Delay'
         *
         * @param jobDelay
         * @return
         */
        public FormValidation doCheckJobDelay(@QueryParameter String jobDelay) {

            //return warning if the field is left empty
            if (StringUtils.isBlank(jobDelay)) {
                return FormValidation.warning(Messages.BossGlobal_DefaultValueWarning());
            } else {
                if (!StringUtils.isNumeric(jobDelay)) {
                    return FormValidation.error(Messages.BossGlobal_JobDelayMustBeNumeric());
                }
            }
            return FormValidation.ok();
        }

        /**
         * On-the-fly validation method for the global property 'OC4J Profiles Path'
         *
         * @param oc4jProfilesPath
         * @return
         */
        public FormValidation doCheckOc4jProfilesPath(@QueryParameter String oc4jProfilesPath) {
            File file = new File(oc4jProfilesPath);
            return checkFile(oc4jProfilesPath, file);
        }

        /**
         * On-the-fly validation method for the global property 'PAM OC4J Profiles Path'
         *
         * @param pamOc4jProfilesPath
         * @return
         */
        public FormValidation doCheckPamOc4jProfilesPath(@QueryParameter String pamOc4jProfilesPath) {
            File file = new File(pamOc4jProfilesPath);
            return checkFile(pamOc4jProfilesPath, file);
        }

        /**
         * On-the-fly validation method for the global property 'GIS Profiles Path'
         *
         * @param gisProfilesPath
         * @return
         */
        public FormValidation doCheckGisProfilesPath(@QueryParameter String gisProfilesPath) {
            File file = new File(gisProfilesPath);
            return checkFile(gisProfilesPath, file);
        }

        /**
         * Check existence of file/directory
         * @param path
         * @param file
         * @return
         */
        public FormValidation checkFile(String path, File file) {
            //return a warning if the field is left empty
            if (StringUtils.isBlank(path)) {
                return FormValidation.warning(Messages.BossGlobal_DefaultValueWarning());
            } else {
                //return error if directory/file does not exist
                if (!file.exists()) {
                    return FormValidation.error(Messages.BossGlobal_InvalidFileOrDirectory());
                } else {
                    //return error if its not a directory
                    if (!file.isDirectory()) {
                        return FormValidation.error(Messages.BossGlobal_InvalidDirectory());
                    }
                }
            }
            return FormValidation.ok();
        }
    }
}
